package com.sjx.jtt809.server.handler;

import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.sjx.jtt809.server.business.BusinessFactory;
import com.sjx.jtt809.server.manager.SlaveLinkManagerJtt809;
import com.sjx.jtt809.server.pojo.BusinessBean;
import com.sjx.jtt809.server.pojo.Response;
import com.sjx.jtt809.server.pojo.command.RequestJtt809_0x9005;
import com.sjx.jtt809.server.pojo.command.ResponseJtt809_0x9002;
import com.sjx.jtt809.server.util.ConstantJtt809Util;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.EventLoop;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;

/**
 * 从链路处理器
 */
public class SlaveLinkServerJtt809Handler extends SimpleChannelInboundHandler<Response> {

    private static final Log logger = LogFactory.get();

    private String ip;

    private int port;

    private int verifyCode;

    private SlaveLinkManagerJtt809 slaveLinkManagerJtt809;

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public int getVerifyCode() {
        return verifyCode;
    }

    public void setVerifyCode(int verifyCode) {
        this.verifyCode = verifyCode;
    }

    public SlaveLinkServerJtt809Handler(String ip, int port, int verifyCode) {
        this.ip = ip;
        this.port = port;
        this.verifyCode = verifyCode;
        this.slaveLinkManagerJtt809 = new SlaveLinkManagerJtt809(ip, port, verifyCode);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Response msg) throws Exception {
        // 收到消息直接打印输出
        logger.info("=====> 【上级平台|接收】指令 = {} ， 数据 = {}", Integer.toHexString(msg.getMsgId()), JSONUtil.toJsonStr(msg));

        // 开启线程执行业务方法
        // ThreadUtil.execute(new BusinessFactory(ctx, msg));
        BusinessFactory.goOn(new BusinessBean(ctx,msg));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 记录下级平台地址与链接
        InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
        ConstantJtt809Util.DOWN_PLATFORM.put(remoteAddress.toString(), ctx);

        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("======> 【上级平台|信息】与下级平台服务器失去连接！");
        InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress();
        ConstantJtt809Util.DOWN_PLATFORM.remove(remoteAddress.toString());

        // 使用过程中断线重连
        final EventLoop eventLoop = ctx.channel().eventLoop();
        eventLoop.schedule(new Runnable() {
            @Override
            public void run() {
                slaveLinkManagerJtt809.start();
            }
        }, 1, TimeUnit.SECONDS);
        ctx.fireChannelInactive();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state().equals(IdleState.READER_IDLE)) {
                logger.info("======> 【上级平台|信息】长时间没收到下级平台推送的数据");
                // 超时关闭channel
                // ctx.close();
            } else if (event.state().equals(IdleState.WRITER_IDLE)) {
                // 发送心跳,保持长连接
                if (ResponseJtt809_0x9002.isIsLoginFlagFromDownPlatform()) {
                    ctx.channel().writeAndFlush(new RequestJtt809_0x9005());

                    logger.info("======> 【上级平台|信息】心跳发送成功!");
                } else {
                    logger.info("======> 【上级平台|信息】下级平台登录失败，不发送心跳!");
                }
            } else if (event.state().equals(IdleState.ALL_IDLE)) {
                logger.info("======> 【上级平台|信息】ALL_IDLE");
            }
        }
        super.userEventTriggered(ctx, evt);
    }
}